﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using SQLToolbox.View.Types;
using System.Reflection;
using SQLToolbox.Lib;
namespace SQLToolbox.View
{
	/// <summary>
	/// This class is a generic dialog used in SQLToolbox.
	/// It shows various user controlls.
	/// If the user control need dialog to display buttons and it wants to interact with those buttons-
	/// the user control needs implement methods - each for one button - which implement the interaction 
	/// logic. Those methods need to be marked with the DialogButton attribute.
	/// If the user control need dialog to return some value - it needs to implement a property which 
	/// returns the value. this property needs to me marked with the DialogValue attribute.
	/// 
	/// If the user contorl wants the dialog to display some title it needs to implement a property called
	/// Title.
	/// </summary>
	public partial class DialogWindow : Window
	{
		PropertyInfo dialogValue = null;
		UserControl uc;
		public DialogWindow()
		{
			InitializeComponent();
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="DialogWindow"/> class.
		/// </summary>
		/// <param name="uc">The uc.</param>
		// TODO - work with priority queue here.
		public DialogWindow(UserControl uc)
		{
			InitializeComponent();
			var type = uc.GetType();
			CreateButtons(uc, type);

			PropertyInfo pi = type.GetProperty("Title");
			if (pi != null)
				this.Title = pi.GetValue(uc, null).ToString();

			
			
			dialogValue = (from p in type.GetProperties()
						  from attr in p.GetCustomAttributes(typeof(DialogValueAttribute), false)
						  select p).ElementAtOrDefault(0);
			
			host.Children.Add(uc);
			this.uc = uc;



		}

		private void CreateButtons(UserControl uc, Type type)
		{
			int i = 0;
			var buttons = new PriorityQueue<Tuple<int, Button>>(new PairIntButtonComparer());

			var querry = from mi in type.GetMethods()
						 from attr in mi.GetCustomAttributes(typeof(DialogButtonAttribute), false)
						 select new { mi, attr };

			foreach (var tuple in querry)
			{

				if ((tuple.mi.ReturnType != typeof(bool?)) ||
											(tuple.mi.GetParameters().Length > 0))
					throw new InvalidOperationException("DialogButtonAttribute is supposed to be set only for methods that return bool? and don't recieve any parameters");

				Button btn = new Button();
				btn.SnapsToDevicePixels = true;
				btn.MinHeight = 23;
				btn.MinWidth = 75;
				btn.Margin = new Thickness(2);
				btn.Padding = new Thickness(5, 2, 5, 2);
				btn.Content = ((DialogButtonAttribute)tuple.attr).Text;
				btn.Visibility = Visibility.Visible;
				string name = string.Format("btn_{0}", i++);
				btn.Name = name;

				MethodInfo temp = tuple.mi;
				btn.Click += (sender, e) =>
				{
					e.Handled = true;
					bool? dr = (bool?)temp.Invoke(uc, null);
					if (dr != null)
					{
						this.DialogResult = dr;
						this.Close();
					}
				};
				buttons.Add(Tuple.Create(((DialogButtonAttribute)tuple.attr).Number, btn));
			}
			while (buttons.Count > 0)
			{
				buttonPanel.Children.Add(buttons.Dequeue().b);
			}
		}

		public object Value
		{
			get
			{
				if (dialogValue != null)
					return dialogValue.GetValue(uc, null);

				return null;
			}
		}
		
		public class PairIntButtonComparer : IComparer<Tuple<int, Button>>
		{

			#region IComparer<Tuple<int,Button>> Members

			public int Compare(Tuple<int, Button> x, Tuple<int, Button> y)
			{
				return x.a - y.a;
			}

			#endregion
		}
	}
}
